//
//  SSLSocketManager.m
//  SSLSocket
//
//  Created by 恒达的mini on 2017/6/10.
//  Copyright © 2017年 孙世龙. All rights reserved.
//

#import "SSLSocketManager.h"
#import "GCDAsyncSocket.h"

#define maxReconnectTime      10   //重连请求最大次数
#define heartTime             30   //每30秒进行一次心跳链接
#define heartText  @"longConnect"  //心跳发送固定字段

@interface SSLSocketManager()<GCDAsyncSocketDelegate>
{
    GCDAsyncSocket  *tcpSocket;   //对象
    int            reConnectTime; //重连次数，
}

@end

@implementation SSLSocketManager
@synthesize delegate;

+ (instancetype)sharedInstance{
    static dispatch_once_t onceToken;
    static SSLSocketManager *instance = nil;
    
    dispatch_once(&onceToken, ^{
        instance = [[self alloc]init];
        
        [instance initSocket];
    });
    return instance;
}
- (void)initSocket{
    tcpSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
}
#pragma mark - public method
/*链接*/
- (BOOL)tcpSocketConnect{
    //先断开
    if (tcpSocket.isConnected) {
        [self tcpSocketCutOff];
    }
    
    NSError *error;
    BOOL ret = [tcpSocket connectToHost:_socketHost onPort:_socketPort withTimeout:-1 error:&error];
    return ret;
}
/*关闭*/
- (void)tcpSocketCutOff{
    tcpSocket.userData = [NSNumber numberWithInt:1];//SocketOffLineByUser报错

    [tcpSocket disconnect];
    
    if (self.connectTimer) {
        [self.connectTimer invalidate];
        self.connectTimer = nil;
    }
}
/*发送*/
- (void)tcpSocketSendInfo:(NSString *)info{
    if (info.length==0) {
        return;
    }
    [self backMessage:[NSString stringWithFormat:@"发送:%@",info]];
    NSData *data = [info dataUsingEncoding:NSUTF8StringEncoding];
    
    [tcpSocket writeData:data withTimeout:-1 tag:0];
}
#pragma mark - GCDAsynSocket Delegate
#pragma mark - 链接成功
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port{
    NSLog(@"连接成功,host:%@,port:%d",host,port);
    
    reConnectTime = 0;
    
    [self readData];
    /*
     1、这是客户端主动发起心跳请求，也可由服务器发起
     2、服务器发起心跳时，请注释掉 心跳计时器相关代码
     */
    if (_openHeartConnect) {
        self.connectTimer = [NSTimer scheduledTimerWithTimeInterval:heartTime
                                                             target:self
                                                           selector:@selector(longConnectToSocket)
                                                           userInfo:nil repeats:YES];
        [self.connectTimer fire];
    }
    
    //返回信息
    [self backMessage:@"TCP连接成功"];
}
#pragma mark - 收到消息
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
    
    NSString *text = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"收到数据%@",text);
//    [self backMessage:[NSString stringWithFormat:@"收到消息:%@",text]];
    //解析数据
    NSDictionary *dataDic = [NSJSONSerialization JSONObjectWithData:data
                                                        options:NSJSONReadingMutableContainers
                                                          error:nil];
    //NSLog(@"解析字典是%@",dataDic);
//    dataDic = [[NSDictionary alloc] init];
//    dataDic = @{@"client_id"    : @"7f0000010b550000154a",
//                @"send_content" : @"　路透社8月10日曾引述匿名美国官员的话称，美国海军驱逐舰“麦凯恩”号周四(10日)在南海进行“自由航行行动”，进入美济礁12海里，以挑战中国对此的领土声索。报道称，这是特朗普政府上台后美国海军在南海的第三次“自由航行行动”。",
//                @"send_type"    : @"",
//                @"type"     : @"bind",};
//    [[NSNotificationCenter defaultCenter] postNotificationName:kSocket_Msg_Notification object:dataDic];

    if ([dataDic allKeys].count>0) {
        [self dealWithTheDataDic:dataDic];
    }
    [self readData];
}
#pragma mark - 发送成功
- (void)socket:(GCDAsyncSocket*)sock didWriteDataWithTag:(long)tag
{
    //NSLog(@"发送成功,tag:%ld",tag);
    //判断是否成功发送，如果没收到响应，则说明连接断了，则想办法重连
    [self readData];
}
#pragma mark - 断开链接
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err{
    NSLog(@"断开连接,host:%@,port:%d",sock.localHost,sock.localPort);
    [self backMessage:@"TCP连接断开"];
    //断线重连
    if (sock.userData==SocketOffLineByServer) {
        //服务器断开重连
        [self reConnectSocket];
    }else {
        //用户主动断开
        reConnectTime = 0;
        return;
    }
}
#pragma mark - 断开重连机制（连续连接10次）
- (void)reConnectSocket {
    //重连10次失败，停止链接
    if (reConnectTime > maxReconnectTime) {
        reConnectTime = 0;
        return;
    }
    
    [self tcpSocketConnect];
    
    reConnectTime++;
}
#pragma mark-----心跳连接
- (void)longConnectToSocket{
    // 根据服务器要求发送固定格式的数据，假设为指令@"longConnect"，但是一般不会是这么简单的指令
    NSString *longConnect = heartText;
    NSData   *dataStream = [longConnect dataUsingEncoding:NSUTF8StringEncoding];
    
    [tcpSocket writeData:dataStream withTimeout:-1 tag:0];
}
#pragma mark - 监听读数据的代理，只能监听10秒，10秒过后调用代理方法  -1永远监听，不超时，但是只收一次消息，
- (void)readData{
    [tcpSocket readDataWithTimeout:-1 tag:0];
}
- (void)backMessage:(NSString*)mes{
    //返回信息
    if (self.delegate&&[self.delegate respondsToSelector:@selector(outputMessage:)]) {
        [self.delegate outputMessage:mes];
    }
}
#pragma mark-------------分类处理socket数据-------------------
/*
 信息类型(1.bind:机器号绑定;2.heart:心跳响应;3.sent_msg:信息推送),
 1、type等于bind 机器号绑定,执行机器号绑定接口
 2、type等于heart 心跳响应,使用tcp链接向服务器发送string数据'on_line'
 3、type等于sent_msg并且send_type等于1 有成员加入或离开分组，在群组列表界面时重新请求群组数据，其他界面忽略
 */
- (void)dealWithTheDataDic:(NSDictionary*)dataDic{
    NSString *type = [dataDic objectForKey:@"type"];
    
    if ([type isEqualToString:@"bind"]) {
        //NSLog(@"获取客户端id=%@",[dataDic objectForKey:@"client_id"]);
        [[NSUserDefaults standardUserDefaults] setObject:[dataDic objectForKey:@"client_id"] forKey:DeviceClientId];
        
        //绑定clientId
        [self startBindDevice];
        
    }else if ([type isEqualToString:@"heart"]){
        //NSLog(@"心跳");
        NSString *longConnect = @"on_line";
        NSData   *dataStream = [longConnect dataUsingEncoding:NSUTF8StringEncoding];
        
        [tcpSocket writeData:dataStream withTimeout:1 tag:1];
        
    }else if ([type isEqualToString:@"send_msg"]){
       // NSLog(@"信息推送");
//        if ([[dataDic objectForKey:@"send_type"] intValue]==1) {
//            NSLog(@"有成员加入或离开分组");
//            //发送消息，刷新群组列表页
//            [[NSNotificationCenter defaultCenter] postNotificationName:kReload_Chat_GroupList_Notification object:nil];
//        }
//        else if([[dataDic objectForKey:@"send_type"] intValue]==2){
//            //收到好友消息
//            [[NSNotificationCenter defaultCenter] postNotificationName:kReload_Chat_Content_Notification object:dataDic];
//        }
        if ([[dataDic objectForKey:@"send_type"] intValue]==3) {//消息推送
            [[NSNotificationCenter defaultCenter] postNotificationName:kSocket_Msg_Notification object:dataDic];
        }
    }
    
}
- (void)startBindDevice{
    //IOS1000000463\7f0000010b5400000003
  HDDeclare  *declare = [HDDeclare sharedDeclare];
//    if (!declare.deviceno)
//    {
//        [HDRootObj machineIDRequestAction];
//        return;
//    }
    NSString *http_server = [NSString stringWithFormat:@"%@/%@",[HDDeclare IP_Request_Header],@"bind_deviceno"];
    NSDictionary *para = @{@"p" :  @"i",
                           @"device_id":declare.deviceno,
                           @"client_id":[NSString stringWithFormat:@"%@",[[NSUserDefaults standardUserDefaults] objectForKey:DeviceClientId]]};
    
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    [manager POST:http_server parameters:para progress:^(NSProgress * _Nonnull uploadProgress) {
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        //
        NSDictionary *responseDict = (NSDictionary *)responseObject;
        //NSLog(@"%@",responseDict);
        if ([responseDict allKeys].count>0&&[[responseDict objectForKey:@"status"] intValue]==1){
           // NSLog(@"绑定机器号成功success");
        }else{
           // NSLog(@"%@",[responseDict objectForKey:@"msg"]);//输出错误信息status=0时
        }
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        //
        //NSLog(@"绑定机器号faild");
    }];
    
}

@end
